package io.github.luons.mediator.dsl.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.github.luons.mediator.core.constant.Constant;
import io.github.luons.mediator.core.enums.Operator;
import io.github.luons.mediator.core.spi.cube.Column;
import io.github.luons.mediator.core.spi.cube.Dimension;
import io.github.luons.mediator.core.spi.cube.Measure;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * WrapperUtils
 *
 * @author : luons
 */
public class WrapperUtils {

    /**
     * Operator add QueryWrapper
     *
     * @param wrapper  LambdaQueryWrapper
     * @param column   column
     * @param operator operator
     * @param value    value
     * @param <T>      entity
     */
    public static <T> void applyCondition(QueryWrapper<T> wrapper, String column, Operator operator, List<Object> value) {
        if (CollectionUtils.isEmpty(value)) {
            return;
        }
        switch (operator) {
            case EQ:
                wrapper.eq(column, value.get(0));
                break;
            case NE:
                wrapper.ne(column, value.get(0));
                break;
            case LT:
                wrapper.lt(column, value.get(0));
                break;
            case LE:
                wrapper.le(column, value.get(0));
                break;
            case GT:
                wrapper.gt(column, value.get(0));
                break;
            case GE:
                wrapper.ge(column, value.get(0));
                break;
            case IN:
                wrapper.in(column, value);
                break;
            case NOT_IN:
                wrapper.notIn(column, value);
                break;
            // case EXIST:
            //     wrapper.isNotNull(column);
            //     break;
            // case NOT_EXIST:
            //     wrapper.isNull(column);
            //     break;
            case ISNULL:
                wrapper.isNull(column);
                break;
            case IS_NOTNULL:
                wrapper.isNotNull(column);
                break;
            case LIKE:
                wrapper.like(column, value.get(0));
                break;
            default:
                throw new IllegalArgumentException("Unsupported operator: " + operator);
        }
    }

    /**
     * Operator add QueryWrapper
     *
     * @param wrapper    LambdaQueryWrapper
     * @param dimensions dimensions
     * @param measures   measures
     * @param <T>        entity
     */
    public static <T> void applyDimension(QueryWrapper<T> wrapper, List<Dimension> dimensions, List<Measure> measures) {
        if (CollectionUtils.isEmpty(dimensions)) {
            return;
        }
        List<String> selectColumns = dimensions.stream()
                .map(dim -> dim.getColumn() + " AS " + dim.getAliasDefault()).collect(Collectors.toList());
        // List<String> selectColumns = dimensions.stream().map(BaseColumn::getColumn).collect(Collectors.toList());
        for (Measure measure : measures) {
            if (Objects.isNull(measure.getColumn())) {
                continue;
            }
            Column col = measure.getColumn();
            if (StringUtils.isBlank(col.getAggregation())) {
                selectColumns.add(col.getColumn() + " AS " + col.getAliasDefault());
                continue;
            }
            selectColumns.add(col.getAggregation() + "(" + col.getColumn() + ") AS " + col.getAliasDefault());
        }
        // TODO next support SUM(a) / COUNT(b)
        wrapper.select(String.join(Constant.COMMA, selectColumns));
        wrapper.groupBy(dimensions.stream().map(Dimension::getColumn).collect(Collectors.toList()));
    }

}
